"""
Case Type   : 资源池化集群系统内部使用工具
Case Name   : 全量备份->增量备份->恢复->failover
Create At   : 2024/04/19
Owner       : @kyleze
Description :
    1.主机上初始化目录
    2.主机上添加备份实例
    3.主机上执行全量备份
    4.执行增量备份
    5.停止集群
    6.主机执行恢复
    7.备机执行恢复
    8.启动集群
    9.执行failover
Expect      :
    1.成功
    2.成功
    3.成功
    4.成功
    5.成功
    6.成功
    7.成功
    8.成功
    9.成功
History     :
"""

import os
import unittest
import time

from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH

from yat.test import Node
from yat.test import macro


@unittest.skipIf(
    "DMS" not in Common().get_sh_result(
    Node("PrimaryDbUser"), f"source {macro.DB_ENV_PATH}; "
    f"cm_ctl query -Cvidp"), "非资源池化环境不执行")
class SharedStorageGsProbackup(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.log.info(f"-----{os.path.basename(__file__)} start-----")
        self.constant = Constant()
        self.primary_sh = CommonSH('PrimaryDbUser')
        self.st1_sh = CommonSH('Standby1DbUser')
        self.st2_sh = CommonSH('Standby2DbUser')
        self.pri_com = Common('PrimaryDbUser')
        self.st1_com = Common('Standby1DbUser')
        self.st2_com = Common('Standby1DbUser')
        self.pri_node = Node(node='PrimaryDbUser')
        self.st1_node = Node(node='Standby1DbUser')
        self.st2_node = Node(node='Standby2DbUser')
        self.database = self.pri_node.db_name
        self.port = self.pri_node.db_port
        self.parent_path = os.path.dirname(macro.DB_INSTANCE_PATH)
        self.backup_path = os.path.join(self.parent_path,
                                        "backupset/backup_dir_027")
        self.instance_name = 'probackup_027'
        self.primary_script = os.path.join(
            macro.SCRIPTS_PATH, "sharestorage_probackup_primary_restore.sh")
        self.standby_script = os.path.join(
            macro.SCRIPTS_PATH, "sharestorage_probackup_standby_restore.sh")
        self.target_path = os.path.join(macro.DB_BACKUP_PATH, 'probackup_005')
        self.log.info("-----检查数据库状态是否正常-----")
        status = self.primary_sh.get_db_cluster_status()
        self.assertTrue("Degraded" in status or "Normal" in status)
        cmd = f'source {macro.DB_ENV_PATH};' \
              f'cat $DSS_HOME/cfg/dss_vg_conf.ini |cut -d ":" -f 1'
        vgname_infor = self.pri_node.sh(cmd).result().strip()
        self.vgname = "+" + vgname_infor.split('\n')[0].strip() + \
                      ",+" + vgname_infor.split('\n')[1].strip()
        self.socket_path = self.pri_com.show_param("ss_dss_conn_path")

    def test_gs_pro_backup(self):
        step = '--step1:主机上初始化目录 expect:成功--'
        self.log.info(step)
        result = self.primary_sh.exec_pro_backup_init(self.backup_path)
        self.log.info(result)
        self.assertTrue(result, "执行失败:" + step)

        step = '--step2:主机上添加备份实例 expect:成功--'
        self.log.info(step)
        result = self.primary_sh.exec_pro_back_add(
            self.backup_path, self.instance_name,
            f"--enable-dss --instance-id 0 --vgname='{self.vgname}'")
        self.log.info(result)
        self.assertTrue(result, "执行失败:" + step)

        step = '--step3:主机上执行全量备份 expect:成功--'
        self.log.info(step)
        result = self.primary_sh.exec_pro_backup_backup(
            self.backup_path, self.instance_name, 'full',
            f"--enable-dss --instance-id 0 --vgname='{self.vgname}' -j 128")
        self.log.info(result)
        self.assertTrue(result, "执行失败:" + step)

        step = '--step4:主机上执行增量备份 expect:成功--'
        self.log.info(step)
        result = self.primary_sh.exec_pro_backup_backup(
            self.backup_path, self.instance_name, 'ptrack',
            f"--enable-dss --instance-id 0 --vgname='{self.vgname}' -j 128")
        self.log.info(result)
        self.assertTrue(result, "执行失败:" + step)
        backupid_msg = result.splitlines()[-1]
        self.log.info(backupid_msg)
        backup_id = backupid_msg.split()[2]
        self.log.info('备份ID为：' + backup_id)

        step = '--step5:停止集群 expect:成功--'
        self.log.info(step)
        result = self.primary_sh.exec_cm_ctl('stop')
        self.log.info(result)
        self.assertIn(self.constant.cm_stop_success_msg, result,
                      "停止集群失败")

        step = '--step6:主机执行恢复 expect 成功--'
        self.log.info(step)
        self.pri_com.scp_file(self.st2_node, self.primary_script,
                              self.target_path)
        cmd = f'source {macro.DB_ENV_PATH};cd {self.target_path};' \
              f'sh sharestorage_probackup_primary_restore.sh'
        result = self.pri_node.sh(cmd).result()
        self.log.info(result)
        self.assertIn('successfully start dssserver', result, "dss启动失败")
        result = self.primary_sh.exec_pro_backup_restore(
            self.backup_path, self.instance_name, backup_id,
            restore_cmd=f'-D {macro.DB_INSTANCE_PATH} -j 128',  get_detail=True)
        self.log.info(result)
        self.assertTrue(result, "主机执行恢复失败")
        self.log.info('获取主机dssserver pid')
        pid = self.primary_sh.get_pid(self.pri_node, "dssserver")
        kill_cmd = f"kill -9 {pid}"
        result = self.pri_node.sh(kill_cmd).result()
        self.log.info(result)
        self.assertIn('', result, "执行失败" + step)

        step = '--step7:备机执行恢复 expect:成功--'
        self.log.info(step)
        self.st1_com.scp_file(self.st2_node, self.standby_script,
                              self.target_path)
        cmd = f'source {macro.DB_ENV_PATH};cd {self.target_path};' \
              f'sh sharestorage_probackup_standby_restore.sh'
        self.log.info('--备1执行恢复--')
        result = self.st1_node.sh(cmd).result()
        self.log.info(result)
        self.assertIn('successfully restore PGDATA', result, "备1恢复失败")
        self.log.info('获取主机dssserver pid')
        pid = self.st1_sh.get_pid(self.st1_node, "dssserver")
        kill_cmd = f"kill -9 {pid}"
        result = self.st1_node.sh(kill_cmd).result()
        self.log.info(result)
        self.assertIn('', result, "执行失败" + step)
        self.log.info('--备2执行恢复--')
        self.st2_com.scp_file(self.st2_node, self.standby_script,
                              self.target_path)
        result = self.st2_node.sh(cmd).result()
        self.log.info(result)
        self.assertIn('successfully restore PGDATA', result, "备2恢复失败")
        self.log.info('获取主机dssserver pid')
        pid = self.st2_sh.get_pid(self.st1_node, "dssserver")
        kill_cmd = f"kill -9 {pid}"
        result = self.st2_node.sh(kill_cmd).result()
        self.log.info(result)
        self.assertIn('', result, "执行失败" + step)

        step = '--step8:启动集群 expect:成功--'
        self.log.info(step)
        result = self.primary_sh.exec_cm_ctl('start')
        self.log.info(result)
        self.assertTrue(result, "执行失败" + step)

        step = '--step9:执行failover expect:成功--'
        self.log.info(step)
        result = self.primary_sh.exec_cm_ctl(
            'stop', '-n 1')
        self.log.info(result)
        self.assertTrue(result, "执行失败" + step)
        time.sleep(30)
        result = self.primary_sh.exec_cm_ctl('start', '-n 1')
        self.log.info(result)
        self.assertIn(self.constant.cm_start_success_msg,
                      result, "执行失败:" + step)
        status = self.primary_sh.get_db_cluster_status()
        self.assertTrue("Normal" in status)
        result = self.primary_sh.execut_db_sql(
            'select * from pg_stat_get_stream_replications()')
        self.assertNotIn('Primary', result, "执行失败:" + step)

    def tearDown(self):
        self.log.info('----清理环境----')
        result = self.primary_sh.exec_cm_ctl('switchover', '-a')
        clear_cmd = f"rm -rf {self.backup_path}"
        self.log.info(clear_cmd)
        clear_msg = self.pri_node.sh(clear_cmd).result()
        self.log.info(result)
        self.log.info(clear_msg)
        self.assertIn(self.constant.cm_switchover_success_msg,
                      result, '恢复环境失败')
        self.assertIn('', clear_msg, '删除目录失败')
        self.log.info(f"-----{os.path.basename(__file__)} end-----")
